package com.wang.utils;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * @Author wangf
 * @Description 分布式锁工具类
 * @Date 2023/9/9 20:56
 */

@Component
public class RedisShareLockUtil {
    @Resource
    private RedisUtils redisUtils;

    //自旋时间
    private Long TIME_OUT = 1000L;

    /**
     * 加锁
     * @param key
     * @param requestId
     * @param time
     * @return
     */
    public boolean lock(String key, String requestId,Long  time) {
        //参数校验
        if (StringUtils.isBlank(key) || StringUtils.isBlank(requestId)||time<0) {
            throw new RuntimeException("分布式加锁参数异常");
        }
        //获取当前时间
        long currentTime = System.currentTimeMillis();
        //设置过期时间
        long outTime = currentTime + TIME_OUT;
        Boolean res=false;
        //加锁自旋
        while(currentTime<outTime){
            //加锁 借助redis的setNx方法
        res = redisUtils.setNx(key, requestId, time, TimeUnit.MILLISECONDS);
        //如果加锁成功
        if(res){
            return true;
        }
        //如果加锁失败，自旋
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        currentTime=System.currentTimeMillis();
        }
        return res;
    }

    /**
     * 解锁
     * @param key
     * @param requestId
     * @return
     */
    public boolean unlock(String key, String requestId) {
        //参数校验
        if (StringUtils.isBlank(key) || StringUtils.isBlank(requestId)) {
            throw new RuntimeException("分布式解锁参数异常");
        }
        try {
            String value = redisUtils.get(key);
            if(requestId.equals(value)){
                redisUtils.del(key);
                return true;
            }
        } catch (Exception e) {
           // log.error("分布式解锁异常", e);
        }
        return false;
    }

    /**
     * 尝试获加锁
     * @param key
     * @param requestId
     * @param time
     * @return
     */
    public boolean tryLock(String key, String requestId, Long time) {
        //参数校验
        if (StringUtils.isBlank(key) || StringUtils.isBlank(requestId)||time<0) {
            throw new RuntimeException("分布式加锁参数异常");
        }
        return redisUtils.setNx(key, requestId, time, TimeUnit.MILLISECONDS);
    }
}
